from django.db.models import fields
from django.db.models.query import QuerySet
from goods.models import SKU, SKUSpecification,GoodsCategory, SPU, SPUSpecification, SpecificationOption
from rest_framework import serializers
from django.db import transaction


class SKUSpecificationSerialzier(serializers.ModelSerializer):
    """
    SKU商品规格
    """
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()
    class Meta:
        model = SKUSpecification
        fields = ['spec_id', 'option_id']
        # fields = '__all__'
        # extra_kwargs = {
        #     'sku': {'read_only': True},
        #     'spec': {'read_only': True},
        #     'option': {'read_only': True}
        # }

class SKUGoodsSerializer(serializers.ModelSerializer):
    """
    SKU商品信息
    """
    # spu_id是关联主表的单一对象的主键隐藏字段
    spu_id = serializers.IntegerField()
    spu = serializers.StringRelatedField()
    # category_id是关联主表的单一对象的主键隐藏字段
    category_id = serializers.IntegerField()
    category = serializers.StringRelatedField()
    # specs=？？？ 关联从表对象的隐藏字段， 从表SKUSpecification
    # 序列化主表的时候，嵌套从表对象的数据
    specs=SKUSpecificationSerialzier(many=True)
    class Meta:
        model = SKU
        # 模型类显示定义的字段，主键隐藏字段，会自动映射
        fields = '__all__'
    # specs记录sku的规格和选项
    # 重写create：因为原本的create方法不能把specs写入中间表SKUSpecification
    def create(self, validated_data):
        specs = validated_data.pop('specs') # 把specs剥离出来，因为新建sku不需要这个字段 
        # 用事务
        with transaction.atomic():
            save_point = transaction.savepoint()
            try:
                sku = SKU.objects.create(**validated_data) # 新建sku主表
                # （根据spec来）新建中间表SKUSpecification数据，来记录sku的规格和选项
                for spec in specs:
                    # spec = {'spec_id':4, 'option_id':8}
                    spec['sku_id'] = sku.id # 加上sku_id: spec = {'sku_id': 1,'spec_id':4, 'option_id':8}
                    SKUSpecification.objects.create(**spec)
            except Exception as  e:
                transaction.rollback(save_point)   
            transaction.savepoint_commit(save_point)
        # 返回
        return sku
    # 重写update，原本的update无法完成中间表的更新
    def update(self, instance, validated_data):
        specs = validated_data.pop('specs')
        with transaction.atomic():
            save_point = transaction.savepoint()
            try:
                sku = super().update(instance, validated_data)
                # 先删除原有的中间表数据， 再插入新的规格和选项
                SKUSpecification.objects.filter(sku_id=sku.id).delete()
                for spec in specs:
                    spec['sku_id'] = sku.id
                    SKUSpecification.objects.create(**spec)
            except Exception as e:
                transaction.rollback(save_point)
            transaction.savepoint_commit(save_point)
        return sku

        


class SKUCategorieSerializer(serializers.ModelSerializer):
    """
    SKU商品三级分类
    """
    class Meta:
        model = GoodsCategory
        # fields = '__all__'
        fields = ['id', 'name']

class SPUSimpleSerializer(serializers.ModelSerializer):
    """
    SPU可选列表数据
    """
    class Meta:
        model = SPU
        fields = ['id', 'name']


class SPUOptionSerializer(serializers.ModelSerializer):
    """
    选项
    """
    class Meta:
        model = SpecificationOption
        fields = ['id', 'value']


class SPUSpecSerialzier(serializers.ModelSerializer):
    """
    SPU规格
    """
    spu_id = serializers.IntegerField()
    spu = serializers.StringRelatedField()
    # 嵌套选项
    options = SPUOptionSerializer(many=True) # 从表SpecificationOption隐藏字段，pecificationOption的外键字段有个related_name=options
    class Meta:
        model = SPUSpecification
        fields = ['id', 'name', 'spu', 'spu_id', 'options']

